package com.sweetcircle.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sweetcircle.annotation.CheckObject;
import com.sweetcircle.annotation.CheckValue;
import com.sweetcircle.annotation.FieldNote;
import com.sweetcircle.annotation.GlobalInterceptor;
import com.sweetcircle.domain.dto.TokenUserInfoDto;
import com.sweetcircle.domain.enums.MessageTypeEnum;
import com.sweetcircle.domain.po.ChatMessage;
import com.sweetcircle.domain.vo.ResponseVO;
import com.sweetcircle.exception.BusinessException;
import com.sweetcircle.service.ChatMessageService;
import com.sweetcircle.utils.AnanUtils;
import com.sweetcircle.utils.RedisComponet;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/chat")
public class ChatController extends ABaseController {

    @Resource
    RedisComponet redisComponet;
    @Resource
    private ChatMessageService chatMessageService;

    @PostMapping("/sendMessage")
    @GlobalInterceptor(checkParams = true)
    public ResponseVO sendMessage(
            @CheckObject(required = true, checkProperties = {"messageType", "contactId", "messageCode"})
            @RequestBody ChatMessage chatMessage,
            HttpServletRequest request) {

        TokenUserInfoDto tokenUserInfoDto = redisComponet.getTokenUserInfoDto(AnanUtils.getAuthorization(request));
        // MessageTypeEnum.FORCE_OFF_LINE.getType().equals(chatMessage.getMessageType()  判断 消息类型是否为强制下线
        // 如果不是异地登录 强制下线 那么就校验 是否登录或者是登录过期
        if (tokenUserInfoDto == null && !MessageTypeEnum.FORCE_OFF_LINE.getType().equals(chatMessage.getMessageType())) {
            throw new BusinessException(600, "用户未登录 或 登录超时 请登录！");
        }
        if (chatMessage.getMessageType() == 2) {
            if (chatMessage.getMessageContent().isEmpty()) {
                throw new BusinessException(400, "消息内容不能为空");
            }

        }
        ChatMessage messageSendDto = chatMessageService.sendMessage(chatMessage, tokenUserInfoDto);
        return successResponseVO(messageSendDto);
    }

    @PostMapping("/sendFileMessage")
    @GlobalInterceptor(checkParams = true)
    public ResponseVO sendFileMessage(
            Integer messageType,
            String userId,
            MultipartFile file,
            HttpServletRequest request) throws Exception {

        TokenUserInfoDto tokenUserInfoDto = redisComponet.getTokenUserInfoDto(AnanUtils.getAuthorization(request));
        // MessageTypeEnum.FORCE_OFF_LINE.getType().equals(chatMessage.getMessageType()  判断 消息类型是否为强制下线
        // 如果不是异地登录 强制下线 那么就校验 是否登录或者是登录过期
        if (tokenUserInfoDto == null) {
            throw new BusinessException(600, "用户未登录 或 登录超时 请登录！");
        }

        if (file.isEmpty()) {
            throw new BusinessException(400, "文件不能为空 请选择一个文件上传！");
        }
        if (messageType == null) {
            throw new BusinessException(400, "缺少参数 messageType ");
        }
        if (userId.isEmpty()) {
            throw new BusinessException(400, "缺少参数 userId ");
        }


        String uploadDirectory = System.getProperty("user.dir") + "/file/message/";
        if (messageType == 201) {
            uploadDirectory = uploadDirectory + userId + "/images/";
        } else if (messageType == 202) {
            uploadDirectory = uploadDirectory + userId + "/video/";
        } else {
            uploadDirectory = uploadDirectory + userId + "/file/";
        }
        File file1 = new File(uploadDirectory);
        if (!file1.exists()) {
            file1.mkdirs();
        }

        //保存文件
        Path destination = Paths.get(uploadDirectory, StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename())));
        File file11 = new File(String.valueOf(destination));
        if (file11.exists()) {
            String hash = calculateMD5(file11);
            String hash2 = calculateMD5(file);
            if (hash.equals(hash2)) {
                return successResponseVO("上传成功");
            }


            destination = Paths.get(uploadDirectory, StringUtils.cleanPath(file.getOriginalFilename()));
        }


        try {
            Files.copy(file.getInputStream(), destination);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        return successResponseVO("上传成功");
    }

    private String calculateMD5(File file) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        try (InputStream is = Files.newInputStream(file.toPath());
             DigestInputStream dis = new DigestInputStream(is, md)) {
            // 获取 file的全部大小
            long fileSize = file.length();
            byte[] buffer;
            if (fileSize > 5 * 1024 * 1024) {
                buffer = new byte[5 * 1024 * 1024];
                return getStr(md, dis, buffer);

            } else {
                buffer = new byte[(int) fileSize];
                return getStr(md, dis, buffer);
            }
        }
    }

    private String calculateMD5(MultipartFile file) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        try (InputStream is = file.getInputStream();
             DigestInputStream dis = new DigestInputStream(is, md)) {
            // 获取 file的全部大小
            long fileSize = file.getSize();
            byte[] buffer;
            if (fileSize > 5 * 1024 * 1024) {
                buffer = new byte[5 * 1024 * 1024];
                return getStr(md, dis, buffer);

            } else {
                buffer = new byte[(int) fileSize];
                return getStr(md, dis, buffer);
            }
        }
    }


    private String getStr(MessageDigest md, DigestInputStream dis, byte[] buffer) throws IOException {
        int read = dis.read(buffer);
        if (read == -1) {
            return null;
        }
        byte[] hashBytes = md.digest();

        StringBuilder sb = new StringBuilder();
        for (byte b : hashBytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    @GetMapping("messageFile")
    @GlobalInterceptor(checkParams = true, checkLogin = true)
    public void messageFile(@CheckValue(required = true) @FieldNote(value = "发送用户ID") @RequestParam(value = "userId") String userId,
                            @CheckValue(required = true) @FieldNote(value = "文件类型") @RequestParam(value = "messageType") Integer messageType,
                            @CheckValue(required = true) @FieldNote(value = "文件名") @RequestParam(value = "fileName") String fileName,
                            HttpServletRequest request,
                            HttpServletResponse response) {
        String uploadDirectory = System.getProperty("user.dir") + "/file/message/";
        File file = null;


        if (messageType == 201) {
            uploadDirectory = uploadDirectory + userId + "/images/";
        } else if (messageType == 202) {
            uploadDirectory = uploadDirectory + userId + "/video/";
        } else {
            uploadDirectory = uploadDirectory + userId + "/file/";
        }
        file = new File(uploadDirectory, fileName);
        if (!file.exists()) {
            throw new BusinessException(400, "文件不存在稍后再试");
        }
        try {
            byte[] bytes1 = Files.readAllBytes(file.toPath());
            response.getOutputStream().write(bytes1);
        } catch (IOException e) {
            throw new BusinessException(400, "文件传输失败 请重试");
        }
    }




    @GetMapping("/getOfflineMessage")
    @GlobalInterceptor(checkParams = true, checkLogin = true)
    public ResponseVO getOfflineMessage(@CheckValue(required = true) @FieldNote(value = "用户ID") @RequestParam(value = "userId") String userId, HttpServletRequest request) {
        List<ChatMessage> list = chatMessageService.list(new LambdaQueryWrapper<ChatMessage>()
                .eq(ChatMessage::getContactId, userId)
                .eq(ChatMessage::getSendStatus, 2)  // 未接收
                .eq(ChatMessage::getStatus, 1)
        );

        // 设置 list 的每个元素的 sendStaus 为 1
        list.forEach(item -> item.setSendStatus(1));


        if (!list.isEmpty()) {
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setSendStatus(1);
            boolean update = chatMessageService.update(chatMessage, new LambdaQueryWrapper<ChatMessage>()
                    .eq(ChatMessage::getContactId, userId)
                    .eq(ChatMessage::getSendStatus, 2)  // 未接收
                    .eq(ChatMessage::getStatus, 1));
            if (!update) {
                throw new BusinessException(400, "获取离线消息失败（更新发送状态失败）");
            }
        }
        return successResponseVO(list);
    }


    @PostMapping("/deleteMessage")
    @GlobalInterceptor(checkParams = true, checkLogin = true)
    public ResponseVO deleteMessage(@CheckObject(required = true, checkProperties = {"sessionId"}) @RequestBody ChatMessage chatMessage, HttpServletRequest request) {
        chatMessageService.deleteMessage(chatMessage);
        return successResponseVO("删除消息成功");
    }

}
